package com.linkwechat.common.utils.http;

import com.alibaba.fastjson.JSON;
import com.linkwechat.common.utils.UrlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

//wjp
@Slf4j
public class HttpUtil {

    private static Integer timeout = 60000;

    private static Integer connectTimeout = 1000;

    private static final String CHARSET_CODE ="utf-8";

    /**
     * get请求
     *
     * @param url
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String doGet(String url) {
        CloseableHttpResponse response = null;
        String result = null;
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            response = httpclient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, "UTF-8");
            }
            EntityUtils.consume(entity);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                response.close();
            }catch (Exception e2){
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * POST请求
     *
     * @param url
     * @param outStr
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String doPost(String url, String outStr){
        CloseableHttpResponse response = null;
        String result = null;
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            if(outStr!=null&&!outStr.isEmpty()){
                httpPost.setEntity(new StringEntity(outStr, "UTF-8"));
            }
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
            //消耗掉response
            EntityUtils.consume(entity);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                response.close();
            }catch (Exception e2){
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送POST请求
     *
     * @param url        目的地址
     * @param parameters 请求参数，Map类型。
     * @return 远程响应结果
     * @throws Exception
     */
    public static String sendPost(String url, Map<String, String> parameters){
        String result = "";// 返回的结果
        BufferedReader in = null;// 读取响应输入流
        PrintWriter out = null;
        StringBuffer sb = new StringBuffer();// 处理请求参数
        String params = "";// 编码之后的参数
        HttpURLConnection httpConn = null;
        try {
            // 编码请求参数
            if (parameters != null && parameters.size() > 0) {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(java.net.URLEncoder.encode(parameters.get(name), "UTF-8"))
                            .append("&");
                }
                String tempParams = sb.toString();
                params = tempParams.substring(0, tempParams.length() - 1);
            }
            // 创建URL对象
            URL connURL = new URL(url);
            // 打开URL连接
            httpConn = (HttpURLConnection) connURL.openConnection();
            // 设置通用属性
            httpConn.setConnectTimeout(timeout);
            httpConn.setReadTimeout(timeout);
            httpConn.setRequestMethod("POST");
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 设置POST方式
            httpConn.setDoInput(true);
            httpConn.setDoOutput(true);
            // 获取HttpURLConnection对象对应的输出流
            out = new PrintWriter(httpConn.getOutputStream());
            // 发送请求参数
            out.write(params);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应，设置编码方式
            in = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "UTF-8"));
            String line;
            // 读取返回的内容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
                if (httpConn != null) {
                    httpConn.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 发送POST请求-json参数
     *
     * @param url  目的地址
     * @param json json参数数据
     * @return 远程响应结果
     */
    public static String sendPostJson(String url, String json) {
        String result = "";// 返回的结果
        BufferedReader in = null;// 读取响应输入流
        PrintWriter out = null;
        StringBuffer sb = new StringBuffer();// 处理请求参数
        HttpURLConnection httpConn = null;
        try {
            // 创建URL对象
            URL connURL = new URL(url);
            // 打开URL连接
            httpConn = (HttpURLConnection) connURL.openConnection();
            // 设置通用属性
            httpConn.setConnectTimeout(timeout);
            httpConn.setReadTimeout(timeout);
            httpConn.setRequestMethod("POST");
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("Content-Type", "application/json");
            // 设置POST方式
            httpConn.setDoInput(true);
            httpConn.setDoOutput(true);
            // 获取HttpURLConnection对象对应的输出流
            out = new PrintWriter(httpConn.getOutputStream());
            // 发送请求参数
            out.write(json);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应，设置编码方式
            in = new BufferedReader(new InputStreamReader(httpConn.getInputStream(), "UTF-8"));
            String line;
            // 读取返回的内容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
                if (httpConn != null) {
                    httpConn.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    public static String doJsonPost(String url,Object params,Map<String,String> header){
        //log.info("请求地址：{},请求参数：{}，请求头：{}",url,JSON.toJSONString(params),JSON.toJSONString(header));
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpPost httpPost = new HttpPost(url);
        // post请求是将参数放在请求体里面传过去的;这里将entity放入post请求体中
        //请求超时 设置   4.3版本之后，是这样设置
        RequestConfig requestConfig =  RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
        httpPost.setConfig(requestConfig);
        String jsonString = JSON.toJSONString(params, true);
        StringEntity entity = new StringEntity(jsonString, "UTF-8");
        httpPost.setEntity(entity);
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setHeader("Connection", "close");

        if(header != null){
            for (Map.Entry<String,String> entry : header.entrySet()) {
                httpPost.setHeader(entry.getKey(),entry.getValue());
            }
        }
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            String resp = EntityUtils.toString(responseEntity);
            //log.debug("接口响应：{}",resp);
            return resp;
        }catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * <p>功能描述: [post form post请求工具,用于form表单请求] </p>
     * @param host    主机ip,端口信息 形如:"http://主机IP:port"
     * @param path    请求路径(说明:@PathVariable注解修饰的参数应包含在path上)
     * @param headers 请求头
     * @param querys  请求参数,不加注解的参数默认为querys(入参为key,value形式的参数)
     * @param bodys   请求体
     * @return
     * @throws IOException
     * @throws ClientProtocolException
     * @Title doPostForm
     */
    public static HttpResponse doPostForm(String host, String path, Map<String, String> headers,
                                          Map<String, String> querys, Map<String, String> bodys) throws ClientProtocolException, IOException {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setConnectionRequestTimeout(timeout)
                .setSocketTimeout(timeout).build();
        HttpPost request = new HttpPost(UrlUtil.buildUrl(host, path, querys));
        //设置请求和传输超时时间
        request.setConfig(requestConfig);
        if (headers != null) {
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }
        }
        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<>();
            for (Map.Entry<String, String> entry : bodys.entrySet()) {
                nameValuePairList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, CHARSET_CODE);
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }
        return httpClient.execute(request);
    }

    /**
     * POST请求
     *
     * @param url
     * @param xmlStr
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String doXmlPost(String url, String xmlStr){
        CloseableHttpResponse response = null;
        String result = null;
        try {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            if(xmlStr!=null&&!xmlStr.isEmpty()){
                httpPost.setEntity(new StringEntity(xmlStr, ContentType.create("application/xml", Consts.UTF_8)));
            }
            response = httpclient.execute(httpPost);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(response.getEntity(), "UTF-8");
            //消耗掉response
            EntityUtils.consume(entity);
        }catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                response.close();
            }catch (Exception e2){
                e2.printStackTrace();
            }
        }
        return result;
    }

}
